/*
* File:   iohandle.h
* Author: Administrator
*
* Created on 2014年9月15日, 下午8:29
*/

#ifndef IO_HANDLE_H_
#define IO_HANDLE_H_

#ifdef    __cplusplus
extern "C" {
#endif

#include "stdint.h"

  /*out ctr*/
  typedef struct
  {
    void(*en)(void);
    void(*dis)(void);
    void(*tog)(void);
    uint8_t(*out_st)(void);
  } out_obj_type;

  /*key handle*/
  typedef struct
  {
    uint8_t read_flt_cnt; //采样滤波计数
    uint8_t b_first_key;  //首个按键
    uint16_t found_time_cnt;
    uint16_t lost_time_cnt;
    uint16_t keep_time_cnt;
    uint32_t val;
    uint32_t old;
    uint32_t edge;
    uint32_t found_edge;
    uint32_t lost_edge;
    uint32_t read;
    uint32_t read_old;
  } key_type;
  void key_st_handle(key_type *key, uint8_t time_pulse);
  void key_st_sample(key_type *key, uint8_t flt_sv, uint32_t key_read);
#define key_st_isr   key_st_sample

  typedef struct
  {
    uint8_t space_sv;   //Y连击有效间隔
    uint8_t serial_sv;  //Y连击次数

    uint8_t space_cnt;
    uint8_t serial_cnt;
    uint8_t key_old;
    uint8_t multi_click_out; //连击输出
    uint8_t edge_found;      //按下边沿
    uint8_t edge_lost;       //弹起边沿
    uint16_t st_keep_cnt;
  } key_click_type;

  uint8_t key_click_handle(key_click_type *obj, uint8_t key_now, uint8_t pulse);

  /*io st*/
  typedef struct
  {
    uint8_t  time_pulse;   //Y--计时脉冲
    uint8_t  sample_pulse; //Y--采样脉冲    
    uint8_t  val;
    uint8_t  old;
    uint8_t found_edge;
    uint8_t lost_edge;
    uint8_t sample_old;
    uint8_t sample_keep_cnt;//0-UINT8_MAX
    uint32_t found_time_cnt;//0-UINT32_MAX
    uint32_t lost_time_cnt; //0-UINT32_MAX
  } in_switch_st_type;

  typedef struct
  {
    struct
    {
      uint8_t  time_pulse : 1;  //计时脉冲
      uint8_t  sample_pulse : 1; //采样脉冲    
      uint8_t  val : 1;
      uint8_t  old : 1;
      uint8_t found_edge : 1;
      uint8_t lost_edge : 1;
      uint8_t sample_old : 1;
    } st;
    uint8_t sample_keep_cnt;//0-UINT8_MAX
    uint16_t found_time_cnt;//0-UINT16_MAX
    uint16_t lost_time_cnt;//0-UINT16_MAX
  } simp_switch_st_type;  //采用位态（节省内存，效率略降），最大计时缩短，功能同in_switch_st_type

  typedef struct
  {
    uint8_t  time_pulse;  //计时脉冲 
    uint8_t  old;
    uint8_t enable_edge;
    uint8_t disable_edge;
    uint32_t enable_time_cnt;//0-UINT32_MAX
    uint32_t disable_time_cnt;//0-UINT32_MAX
  } out_st_type;

  typedef struct
  {
    uint8_t  out;  //计时脉冲 
    uint8_t  old;
    uint8_t enable_edge;
    uint8_t disable_edge;
    uint32_t enable_time_cnt;//0-UINT32_MAX
    uint32_t disable_time_cnt;//0-UINT32_MAX
  } out_stv2_type;

  typedef struct
  {
    struct
    {
      uint8_t  time_pulse : 1;  //计时脉冲 
      uint8_t  old : 1;
      uint8_t enable_edge : 1;
      uint8_t disable_edge : 1;
    } st;
    uint16_t enable_time_cnt;//0-UINT16_MAX
    uint16_t disable_time_cnt;//0-UINT16_MAX
  } simp_out_st_type;

  void in_switch_handle(in_switch_st_type *swobj, uint8_t sw_now);  //内部滤波次数固定值6，输入可以是0和任意非零状态
  void simp_switch_handle(simp_switch_st_type *swobj, uint8_t sw_now);  //内部滤波次数固定值6，输入必须是0和1两个状态
  void out_st_handle(out_st_type *obj, uint8_t out_now);//允许多任务使用
  void out_stv2_handle(out_stv2_type *obj, uint8_t time_pulse);//允许多任务使用
  void simp_out_st_handle(simp_out_st_type *obj, uint8_t out_now); //不可在多任务中使用

  /*--------------------------------------------------------------------------------------------------------------------------*/
  /*rot st*/
  typedef struct
  {
    uint8_t a_st;
    uint8_t a_old;
    uint8_t b_st;
    uint8_t b_old;
    uint8_t b_clock;
    uint8_t b_unti_clock;
    uint16_t clock_none_time_cnt; //间隔计时器，每次调用递增，检测到任意有效旋转，记录该值到 clock_interval
    uint16_t clock_interval;      //间隔
  } rot_key_type;

  void rot_key_handle(rot_key_type *key, uint8_t a, uint8_t b);

  /*--------------------------------------------------------------------------------------------------------------------------*/
  typedef struct
  {
    uint8_t st;     //当前有效状态
    int8_t flt_cnt; //滤波计数，负方向为无效状态，正方向为有效状态，回差带内保持(包含边界)
  } io_flt_type;

  typedef struct
  {
    struct
    {
      uint8_t val : 1;     //当前有效状态
      uint8_t old : 1;
      uint8_t edge : 1;
      uint8_t edge_found : 1;
      uint8_t edge_lost : 1;
    } st;

    int8_t flt_cnt; //滤波计数，负方向为无效状态，正方向为有效状态，回差带内保持(包含边界)
  } io_flt_edge_type;

  typedef struct
  {
    struct
    {
      uint8_t val : 1;     //当前有效状态
      uint8_t old : 1;
      uint8_t edge : 1;
      uint8_t edge_found : 1;
      uint8_t edge_lost : 1;
      uint8_t pulse_sample : 1; //采样脉冲
      uint8_t pulse_time : 1; //计时脉冲
    } st;

    int8_t flt_cnt; //滤波计数，负方向为无效状态，正方向为有效状态，回差带内保持(包含边界)
    uint16_t found_time_cnt;
    uint16_t lost_time_cnt;
  } io_flt_ext_type;

  typedef struct
  {
    struct
    {
      uint8_t val : 1;     //当前有效状态
      uint8_t old : 1;
      uint8_t edge : 1;
      uint8_t edge_found : 1;
      uint8_t edge_lost : 1;
    } st;

    int8_t flt_cnt; //滤波计数，负方向为无效状态，正方向为有效状态，回差带内保持(包含边界)
    uint16_t found_time_cnt;
    uint16_t lost_time_cnt;
  } io_flt_extv2_type;

  typedef struct
  {
    struct
    {
      uint8_t val : 1;     //当前有效状态
      uint8_t old : 1;
      uint8_t edge : 1;
      uint8_t edge_found : 1;
      uint8_t edge_lost : 1;
    } st;
    uint8_t lost_keep_sv, found_keep_sv;  //cnt达到指定sv数，flt_cnt计数一次，0和1均为1次
    uint8_t lost_keep_cnt, found_keep_cnt;
    int8_t flt_cnt; //滤波计数，负方向为无效状态，正方向为有效状态，回差带内保持(包含边界)
    uint16_t found_time_cnt;
    uint16_t lost_time_cnt;
  } io_flt_extv3_type;

  uint8_t io_flt(io_flt_type *io_obj, int8_t flt_sv, uint8_t st_now); //flt_sv 滤波设定，回差带为 (-sv~sv)  ,输出状态改变需要1+2*sv个持续输入
  uint8_t io_flt_edge(io_flt_edge_type *io_obj, uint8_t flt_pulse, int8_t flt_sv, uint8_t st_now);
  uint8_t io_flt_ext(io_flt_ext_type *io_obj, int8_t flt_sv, uint8_t st_now); //flt_sv 滤波设定，回差带为 (-sv~sv)  ,输出状态改变需要1+2*sv个持续输入
  uint8_t io_flt_extv2(io_flt_extv2_type *io_obj, uint8_t flt_pulse, uint8_t time_pulse, int8_t flt_sv, uint8_t st_now);//对称回差滤波
  uint8_t io_flt_extv3(io_flt_extv3_type *io_obj, uint8_t flt_pulse, uint8_t time_pulse, int8_t flt_sv, uint8_t st_now);//非对称回差滤波

  /*---io group filter----*/
  typedef struct
  {
    uint8_t val;
    uint8_t val_old;
    uint8_t read_old;
    uint8_t edge;
    uint8_t edge_found;
    uint8_t edge_lost;
    uint8_t flt_cnt;
  } io8_flt_type;

  typedef struct
  {
    uint16_t val;
    uint16_t val_old;
    uint16_t read_old;
    uint16_t edge;
    uint16_t edge_found;
    uint16_t edge_lost;
    uint8_t flt_cnt;
  } io16_flt_type;

  typedef struct
  {
    uint32_t val;
    uint32_t val_old;
    uint32_t read_old;
    uint32_t edge;
    uint32_t edge_found;
    uint32_t edge_lost;
    uint8_t flt_cnt;
  } io32_flt_type;

  void io8_flt(io8_flt_type *io_obj, uint8_t flt_sv, uint8_t read_now);
  void io16_flt(io16_flt_type *io_obj, uint8_t flt_sv, uint16_t read_now);
  void io32_flt(io32_flt_type *io_obj, uint8_t flt_sv, uint32_t read_now);

  /*---io group filter , just value----*/
  typedef struct
  {
    uint8_t val;
    uint8_t read_old;
    uint8_t flt_cnt;
  } io8_simp_flt_type;

  typedef struct
  {
    uint16_t val;
    uint16_t read_old;
    uint8_t flt_cnt;
  } io16_simp_flt_type;

  typedef struct
  {
    uint32_t val;
    uint32_t read_old;
    uint8_t flt_cnt;
  } io32_simp_flt_type;

  void io8_simp_flt(io8_simp_flt_type *io_obj, uint8_t flt_sv, uint8_t read_now);
  void io16_simp_flt(io16_simp_flt_type *io_obj, uint8_t flt_sv, uint16_t read_now);
  void io32_simp_flt(io32_simp_flt_type *io_obj, uint8_t flt_sv, uint32_t read_now);




  /*---signal info creat----*/
  typedef struct
  {
    uint8_t sig_new; //外部更新
    uint8_t sig;
    uint8_t sig_old;
    uint8_t edge, edge_found, edge_lost;
    uint16_t found_time_cnt;
    uint16_t lost_time_cnt;
  } io_signal_type;
  uint8_t io_signal_info_handle(io_signal_type *io_obj, uint8_t time_pulse);

  /*---不连续输入滤波----*/
  typedef struct
  {
    uint8_t st;          // RO 输出
    int8_t flt_cnt;      // RO
    uint16_t period_cnt; // RO || >=period_sv 时判定并回零
    uint16_t active_cnt; // RO || >=active_sv 时判定为有效周期
    uint8_t st_old;      // RO

    uint16_t period_sv; //Y--检测周期
    uint16_t active_sv; //Y--一个周期内，有效数大于等于该值时判定为有效，否则无效
    int8_t flt_sv;      //Y--回差数 //以period_sv作为一个滤波周期
    uint8_t flt_pulse;  //Y--采样脉冲
    uint8_t time_pulse; //Y--计时脉冲

    uint8_t found_edge, lost_edge; //RO
    uint16_t found_time; //RO
    uint16_t lost_time;  //RO
  } discont_in_flt_type;

  uint8_t discont_in_flt(discont_in_flt_type *obj, uint8_t in_val);

  uint8_t ad_io_creat(uint8_t sample_old, uint16_t ad_true, uint16_t ad_false, uint16_t ad_now);

  /*--------------------------------------------------------------------------------------------------------------------------*/
  typedef struct
  {
    uint8_t out;       //RO
    uint8_t en_edge;   //RO
    uint8_t dis_edge;  //RO
    uint8_t en_req;    //Y手动开启请求
    uint8_t dis_req;   //Y手动停止请求
    uint32_t en_time;  //RO //内部计数最大为2^31，溢出归零
    uint32_t dis_time; //RO //内部计数最大为2^31，溢出归零
  } out_sw_type;;
  /* time_sv 设为0不切换该状态,对应req同时失效.设为其他值保持设定数值脉冲数，设定值>2^31时，保持在该状态，除非手动req    */
  /* pulse 为计时脉冲                                           */
  uint8_t out_sw_manage(out_sw_type * out_obj, uint32_t en_time_sv, uint32_t dis_time_sv, uint8_t pulse);

  /*--------------------------------------------------------------------------------------------------------------------------*/
  typedef struct
  {
    uint8_t out;
    uint8_t err;
    uint16_t en_time;
    uint16_t dly_time;
  } wt_add_type;;

  /* ot_time_sv  为0时无补水功能，强制关闭输出 */
  /* pulse 为计时脉冲                                           */
  uint8_t wt_add_manage(wt_add_type * out_obj, uint8_t wt_st, uint16_t ot_time_sv, uint16_t dly_time_sv, uint8_t pulse);

  /*-------------------------------------------------------------------------------------------------------------------------*/
  typedef struct
  {
    uint8_t out0;    //X
    uint8_t out1;    //X
    uint8_t mode;    //Y 0-关闭，1out0,2-out1, 其他切换
    uint8_t out_sel; //X
    int32_t out0_en_time;   //X
    int32_t out0_dis_time;  //X
    int32_t out1_en_time;   //X
    int32_t out1_dis_time;  //X
    int32_t delay_cnt;  //X
    int32_t dev_off_min_time;  //Y 设备最小停机时间
  } dev_double_sw_type;;

  /*****************************************************************************-/
  * @brief   Double cool time handle.
  *          switch_time 必须大于 switch_time_befor+mintime，否则将强制switch_time = switch_time_befor+mintime
  * @param   dev： obj
  * @param   switch_time_set : switch time
  * @param   switch_time_befor : 正数 before-time, 负数delay-time
  * @param   pulse : 计时脉冲
  *****************************************************************************/
  void dev_double_sw(dev_double_sw_type * dev, int32_t switch_time_set, int32_t switch_time_befor, uint8_t pulse);

  /*----正反转控制----*/
  typedef struct
  {
    uint8_t st;
    uint8_t st_start;
    uint32_t cct_set;
    uint32_t nct_set;
    uint32_t sot_set;
    uint32_t spd_now;
    uint32_t cnt;
  } nc_cc_sw_type;

#define C_ST_NC_STOP      0
#define C_ST_CC_RUN       1
#define C_ST_CC_STOP      2
#define C_ST_NC_RUN       3
  //顺序为 C_ST_NC_STOP->C_ST_CC_RUN->C_ST_CC_STOP->C_ST_NC_RUN, 某段时间设为0则跳过,STOP不可跳过，0时如果切换方向也要等待spdnow为0----
  //cct和nct同时为0时强制为start输出----
  uint8_t nc_cc_sw_handle(nc_cc_sw_type *obj, uint8_t en, uint8_t pulse);

  /*----加减速控制----*/
  typedef struct
  {
    uint32_t spd_now;
    uint32_t spd_set;
    uint32_t spd_out;
    uint32_t spd_up;
    uint32_t spd_dn;
    uint32_t spd_rl;
    uint8_t pwm_out_under_min; //输出小于下限值标记----
  } spd_inc_type;

  uint32_t  spd_inc_handle(spd_inc_type * obj, uint8_t pulse);

  /*----输出故障检测-回路电流状态----*/
  typedef struct
  {
    uint16_t ad_val; //Y ad值
    uint16_t ad_set; //Y 阀值

    //电周期内部处理
    uint8_t elec_period; //Y 电周期，对于50Hz，应设为20ms对应的ticks
    uint8_t elec_effective; //Y 一个电周期内，有效信号数最小值----
    uint8_t elec_tick_cnt; //X
    uint8_t elec_found_cnt; //X
    uint8_t elec_found_keep; //X
    uint8_t out_st_old;//X

    //-以下计时单位为控制周期-
    int8_t short_st; //X 一个控制周期内的 short 数-
    int8_t open_st;  //X 一个控制周期内的 open 数-
    int8_t short_st_cnt; //X 输出结果，记录short错误周期数（控制周期）-
    int8_t open_st_cnt;  //X 输出结果，记录open错误周期数（控制周期）-
    int8_t st_cnt_max; //Y 应大于等于2，当错误累计数达到边界时，short/open out is marked
    int8_t short_out; //X 状态输出-
    int8_t open_out;  //X 状态输出-

    //-以下计时单位为电周期-
    uint16_t out_st_keep_cnt; //X输出状态保持计数器-
    uint16_t check_delay;     //Y 一般设为1,输出状态切换后，延时一定电周期数后开始检测-

    //out prt
    uint16_t out_period; //Y pid周期,单位为调用周期-
    uint16_t out_cnt;    //X 单位为调用周期-
  } out_current_check_type;

  extern void current_async_check_handle(out_current_check_type * obj, uint8_t out_st);
  /*- 同步检测，每个输出相位点调用，period指示pid周期，单位为半个电周期-*/
  void current_sync_check_handle(out_current_check_type * obj, uint8_t out_st, uint8_t sync); //sync 参数无意义，仅用于占位-

  /*--------------------------------------------------------------------------*
  * 半波检测相位同步
  * 如果信号不对称，输入电平较短的状态应为1
  * 对于50/60Hz信号，建议检测周期为0.5ms，采样信号进行2级回差滤波
  * out指示输出相位点
  *---------------------------------------------------------------------------*/
  typedef struct
  {
    int8_t signal_flt;
    uint8_t signal_st;
    uint8_t signal_old; //X信号记录-
    int8_t phase; //Y输出相位-
    int8_t wide; //X信号宽度，仅用于观测-
    int8_t period;//X
    int8_t period1, period2;//X
    int8_t cnt; //X相位计数--
    int8_t time_out_set; //Y相位计数超时-
    uint8_t err; //X错误标记-
    uint8_t out_at_sig;//X
    uint8_t out_at_sig_none;//X
    uint8_t out;//X
    uint16_t period_keep_cnt;
  } half_ac_sync_out_point_type;

  uint8_t half_ac_sync_out_point_handle(half_ac_sync_out_point_type * obj, uint8_t signal);

  typedef struct
  {
    uint8_t notice_micro_req; //输出次数请求。周期4，方波50%输出-
    uint8_t notice_short_req; //输出次数请求。周期8，方波50%输出-
    uint8_t notice_mid_req;   //输出次数请求。周期16，方波50%输出-
    uint8_t notice_long_req;  //输出次数请求。周期32，方波75%输出-
    uint8_t pulse_cnt; //base bpulse
    uint8_t b_beep_st; //输出状态-
  } beep_notice_type;

  void beep_notice_handle(beep_notice_type *obj, uint8_t bpulse);

  /*--------------------------------------------------------------------*
  *半双工单线通信
  *高位在前
  *为简化编码，最高位数据必须为0
  *IO必须为开漏或弱上拉输出
  *发送间隔至少上次数据尾部32个时钟
  *接收间隔至少16时钟，发送结束后可立即接收
  *---------------------------------------------------------------------*/

  typedef struct
  {
    uint8_t sample_time_cnt;
    uint8_t idle_time_cnt;

    int8_t in_flt;
    int8_t in_st;

    uint8_t bit_cnt;
    uint8_t bit_sv;
    uint8_t b_rx_ne;

    uint8_t snd_st;
    uint8_t rcv_st;

    uint8_t rcv_allow;
    uint8_t tx_allow;

    uint32_t rx_shift;
    uint32_t rx;
    uint32_t tx;

    void(*tx_out)(uint8_t st);
    uint8_t(*rx_in)(void);
    void(*io_dir)(uint8_t dir); //0r1w
  } dig_encode_type;

  void dig_encode_handle(dig_encode_type *obj);
  uint32_t dig_encode_read(dig_encode_type *obj);
  void dig_encode_write(dig_encode_type *obj, uint32_t dat);

  /*-------------------------------------------------------------------------------------------------------------------------*/
  typedef struct
  {
    uint8_t run_st;//Y
    uint8_t out;//X
    int8_t dir; //X -1下降，1上升，0未知
    uint8_t dir_keep_cnt; //X
    uint8_t dir_keep_sv; //Y

    int16_t sv; //Y
    int16_t pv; //Y
    int16_t en_offset; //Y
    int16_t dis_offset; //Y
    int16_t dir_zone; //Y
    int16_t min; //X
    int16_t max; //X
  } comp_out_type;

  uint8_t comp_out_handle(comp_out_type *obj, uint8_t dir_adj_pulse);      //正作用
  uint8_t comp_out_nev_handle(comp_out_type *obj, uint8_t dir_adj_pulse);  //反作用

#ifdef    __cplusplus
}
#endif

#endif    /* IO_HANDLE_H_ */

